package main;

import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.*;
import java.awt.image.BufferedImage;

import javax.swing.*;

public class MousePanel extends JPanel
{
	static private final int BLACK = 0xFF000000;
	static private final int WHITE = 0xFFFFFFFF;
	private BufferedImage image;
	private Graphics2D g2d;
	private final int WIDTH;
	private final int HEIGHT;
	private MouseListener mouseListener;
	private MouseMotionListener mouseMotionListener;
	
	public MousePanel( int width, int height )
	{
		this.WIDTH = width;
		this.HEIGHT = height;
		
		Dimension dim = new Dimension( WIDTH, HEIGHT );
		this.setPreferredSize( dim );
		image = new BufferedImage( WIDTH, HEIGHT, BufferedImage.TYPE_INT_ARGB );
		g2d = image.createGraphics();
		g2d.fillRect( 0, 0, WIDTH, HEIGHT );
	}
	
	public void initialize()
	{
		createListeners();
		registerListeners();
	}
	
	public void registerListeners()
	{
		// ensures that this is not called before createListeners()
		if( mouseListener == null )
			throw new IllegalStateException( 
					"MousePanel.registerListeners(): not initialized()" );
		addMouseListener( mouseListener );
		addMouseMotionListener( mouseMotionListener );
	}
	
	public void unregisterListeners()
	{
		// ensures that this is not called before createListeners()
		if( mouseListener == null )
			throw new IllegalStateException(
					"MousePanel.unregisterListeners(): not initialized()" );
		removeMouseListener( mouseListener );
		removeMouseMotionListener( mouseMotionListener );
	}
	
	public void paintComponent( Graphics g )
	{
		super.paintComponents( g );
		g.drawImage( image, 0, 0, null );
	}
	
	public void clear( Color color )
	{
		g2d.setColor( color );
		g2d.fillRect( 0, 0, WIDTH, HEIGHT );
		repaint();
	}
	
	private boolean isARGBColor( Point p, int argb )
	{
		return ( image.getRGB( p.x, p.y ) == argb );
	}
	
	private void drawSquare( Point point, Color color )
	{
		int x = ((point.x >> 4) << 4);
		int y = ((point.y >> 4) << 4);
		
		g2d.setColor( color );
		g2d.fillRect( x, y, 16, 16 );
		repaint();
	}
	
	private void createListeners()
	{
		mouseListener = new MouseAdapter()
		{
			public void mousePressed( MouseEvent event )	// run on EDT
			{
				// select the current square (set to black)
				Point point = event.getPoint();
				if( isARGBColor( point, WHITE ))
					drawSquare( point, Color.BLACK );
			}
			
			public void mouseClicked( MouseEvent event )	// run on EDT
			{
				// unselect the current square when double clicked (set to white)
				if( event.getClickCount() >= 2 )
				{
					Point point = event.getPoint();
					if( isARGBColor( point, BLACK ))
						drawSquare( point, Color.WHITE );
				}
			}
		};
		
		mouseMotionListener = new MouseMotionListener()
		{
			public void mouseMoved( MouseEvent event )		// run on EDT
			{
				// set the mouse cursor to cross hairs if it is inside
				// a black rectangle
				
				Point point = event.getPoint();
				if( isARGBColor( point, BLACK ))
					setCursor( Cursor.getDefaultCursor() );
				else
					setCursor( Cursor.getPredefinedCursor( Cursor.CROSSHAIR_CURSOR) );
			}
			
			public void mouseDragged( MouseEvent event )	// run on EDT
			{
				// this space intentionally left blank
			}
		};
	}
}
